查看原文
其他

Android的毛玻璃模糊效果,我使用OpenCV来搞

2017-10-19 JerryloveEmily Android技术经验分享

作者:JerryloveEmily

地址:http://www.jianshu.com/p/d0d7809007a1

声明:本文是JerryloveEmily原创,已获其授权发布,未经原作者允许请勿转载

开始学习OpenCV,毛玻璃模糊效果目前网上流行的有三种办法:

1、使用java来编写一长串的像素处理办法算法来改变bitmap(性能教差,而且一堆算法代码,难理解,不优雅)

2、使用C语言的方式同样使用和java一样的算法来实现(性能好,同样一堆算法代码难理解,也不优雅)

3、使用RenderScript这个有Api版本的限制。

现在我们可以利用OpenCV框架中滤波算法来实现图片的模糊虚化。

准备工作

先到OpenCV官网, 下载Android平台的sdk包: http://www.opencv.org  

解压后:
sdk目录里是openCV的一些动态库,cmake构建文件,以及java的一些api。

新建一个支持NDK的工程:

配置集成OpenCV库到工程:

我这里只编译支持了armeabi,cpu架构的平台,需要在app,module的build.gradle中做一些修改:

对了这里我使用AS自带的cmake工具来构建NDK库的链接和编译的支持,所以不需要再写Android.mk的配置文件,这里配置下CMakeLists.txt就可以,更加简单:

# For more information about using CMake with Android Studio, read the

# documentation: https:

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# 添加我们自己要编译的so库,以及源码文件
add_library(
            image_process
            SHARED
            src/main/cpp/image_process.cpp )

# 增加opencv库
add_library( opencv_java3 SHARED IMPORTED )
# 编译的平台是armeabiif(${ANDROID_ABI} STREQUAL "armeabi")# 设置动态库文件的路径属性set_target_properties(
   opencv_java3
   PROPERTIES IMPORTED_LOCATION
   ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libopencv_java3.so
   )endif(${ANDROID_ABI} STREQUAL "armeabi")# opencv库的头文件路径设置,在此是opencv-sdk的路径,当然你也可以把include目录拷贝到工程中include_directories(
   D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/include
)find_library( # Sets the name of the path variable.
             log-lib

             # Specifies the name of the NDK library that
             # you want CMake to locate.
             log )# 需要链接的库target_link_libraries( # Specifies the target library.
                      image_process
                      opencv_java3
                      # Links the target library to the log library
                      # included in the NDK.
                      ${log-lib} )

上面的添加依赖库,和自己要编译的so库的写法都是差不多的,就是这些套路。(自古深情留不住,总是套路得人心)
同时把sdk中libopencv_java3.so文件拷贝到对应的工程目录下我这里是jniLibs为了方便不然还得配置gradle修改source目录的映射路径:


编写java层的对外开发调用api


public class ImageProcessUtils {

 
   public static Bitmap blur(Bitmap srcBitmap){
       
       int width = srcBitmap.getWidth();
       int height = srcBitmap.getHeight();
       
       int[] pixels = new int[width * height];
       
       srcBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
       
       blurImage(pixels, width, height);
       
       Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
       
       newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
       return newBitmap;
   }

   
   public static native void blurImage(int[] pixels, int w, int h);

   
   static {
       System.loadLibrary("image_process");
       System.loadLibrary("opencv_java3");
   }
}


接下来是在NDK中使用opencv来实现图片的毛玻璃化


#include <jni.h>

#include <android/log.h>
#include <opencv2/opencv.hpp>    // 引入opencv库头文件
#include <opencv2/highgui/highgui.hpp> // 引入opencv图形界面,暂时没用到

// 定义了log日志宏函数,方便打印日志在logcat中查看调试
#define TAG "Jerry-NDK-Image-Pro"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__)

using namespace cv;

extern "C"
JNIEXPORT void JNICALL
Java_com_jerry_jerryopencvdemo_imageprocess_ImageProcessUtils_blurImage(
       JNIEnv *env,
       jclass jcls,
       jintArray jarr_pixels,
       jint j_width,
       jint j_height) {

   // 获取java中传入的像素数组值,jintArray转化成jint指针数组
   jint *c_pixels = env->GetIntArrayElements(jarr_pixels, JNI_FALSE);
   if(c_pixels == NULL){
       return;
   }

   LOGE("图片宽度:%d, 高度:%d", j_width, j_height);

   // 把c的图片数据转化成opencv的图片数据
   // 使用Mat创建图片
   Mat mat_image_src(j_height, j_width, CV_8UC4, (unsigned char*) c_pixels);
   // 选择和截取一段行范围的图片
   Mat temp = mat_image_src.rowRange(j_height / 3, 2 * j_height / 3);
   // 方框滤波
//    boxFilter(temp, temp, -1, Size(85, 85));
   // 均值滤波
   blur(temp, temp, Size(85, 85));
   // 使用高斯模糊滤波
//    GaussianBlur(temp, temp, Size(45, 13), 0, 0);
   // 将opencv图片转化成c图片数据,RGBA转化成灰度图4通道颜色数据
   cvtColor(temp, temp, CV_RGBA2GRAY, 4);

   // 更新java图片数组和释放c++中图片数组的值
   env->ReleaseIntArrayElements(jarr_pixels, c_pixels, JNI_FALSE);
}


原图:

毛玻璃后效果图:

简单的利用了滤波算法函数处理,来达到毛玻璃的效果,当然opencv的强大远远不限于此。关于opencv进一步的学习使用还会继续记录在博客中。


推荐阅读

1、编程语言高质量资料(视频+文档+实战)| 学习资料分享 07

2、Android DataBinding & MVVM

3、为什么程序员没有职业资格证




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存